package com.kevin.service.util;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

/**
 * page read listener
 *
 * @author syh
 */
public class PageReadListener<T> implements ReadListener<T> {
    /**
     * Single handle the amount of data
     */
    public static final int BATCH_COUNT = 100;
    /**
     * Temporary storage of data
     */
    private List<T> cachedDataList = new ArrayList<>(BATCH_COUNT);
    /**
     * Temporary storage of data
     */
    private List<Map<Integer, ReadCellData<?>>> cacheHeaderList = new ArrayList<>();
    /**
     * consumer
     */
    private final Consumer<List<T>> consumer;

    // 默认为1
    public int headerNum = 1;
    /**
     * header consumer
     */
    private final Consumer<List<Map<Integer, ReadCellData<?>>>> headerConsumer;


    public PageReadListener(Consumer<List<T>> consumer) {
        this.consumer = consumer;
        this.headerConsumer = null;
    }

    public PageReadListener(Consumer<List<Map<Integer, ReadCellData<?>>>> headerConsumer, Consumer<List<T>> consumer) {
        this.consumer = consumer;
        this.headerConsumer = headerConsumer;
    }

    public PageReadListener(int headerNum, Consumer<List<Map<Integer, ReadCellData<?>>>> headerConsumer, Consumer<List<T>> consumer) {
        this.headerNum = headerNum;
        this.consumer = consumer;
        this.headerConsumer = headerConsumer;
    }

    @Override
    public void onException(Exception e, AnalysisContext analysisContext) throws Exception {
        throw e;
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        cacheHeaderList.add(headMap);
        if (cacheHeaderList.size() >= headerNum) {
            headerConsumer.accept(cacheHeaderList);
            cacheHeaderList.clear();
        }
    }


    @Override
    public void invoke(T data, AnalysisContext context) {
        cachedDataList.add(data);
        if (cachedDataList.size() >= BATCH_COUNT) {
            consumer.accept(cachedDataList);
            cachedDataList.clear();
            cachedDataList = new ArrayList<>(BATCH_COUNT);
        }
    }

    @Override
    public void extra(CellExtra cellExtra, AnalysisContext analysisContext) {

    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (CollectionUtils.isNotEmpty(cachedDataList)) {
            consumer.accept(cachedDataList);
        }
    }

    @Override
    public boolean hasNext(AnalysisContext analysisContext) {
        return true;
    }

}
